home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
Menu.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-16
|
13KB
|
640 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "Menu.h"
#include "Class.h"
#include "OrdColl.h"
#include "String.h"
#include "Window.h"
#include "CollView.h"
#include "TextItem.h"
#include "Look.h"
#include "Box.h"
static int menulevel;
//---- MenuButtonItem ----------------------------------------------------------
NewMetaImpl0(MenuButtonItem, StateButton);
MenuButtonItem::MenuButtonItem(int id, char *l, char *s) : StateButton(id, state)
{
SetLabel(l);
SetShortCut(s);
SetFlag(eVObjVFixed|eVObjHFixed);
}
MenuButtonItem::MenuButtonItem(int id, VObject *l, char *s) : StateButton(id, state)
{
Add(l);
SetShortCut(s);
SetFlag(eVObjVFixed|eVObjHFixed);
}
Metric MenuButtonItem::GetMinSize()
{
return gLook->MenuItemLayout()->GetMinSize(this);
}
void MenuButtonItem::SetOrigin(Point at)
{
VObject::SetOrigin(at);
gLook->MenuItemLayout()->SetOrigin(this, at);
}
void MenuButtonItem::SetExtent(Point e)
{
CompositeVObject::SetExtent(e);
}
void MenuButtonItem::DrawInner(Rectangle, bool highlight)
{
int code= state;
if (state > 0)
SETBIT(code, 2);
if (highlight)
SETBIT(code, 3);
if (Enabled())
SETBIT(code, 5);
gLook->MenuItemLayout()->Adorn(this, contentRect, code);
}
char *MenuButtonItem::AsString()
{
return At(0)->AsString();
}
void MenuButtonItem::SetShortCut(char *sc)
{
if (sc) {
char *s= form("\327%c", sc[0]);
if (Size() > 1) {
TextItem *t= (TextItem*) At(1);
t->SetString(s);
} else
Add(new TextItem(s));
}
}
void MenuButtonItem::SetLabel(char *s)
{
if (s) {
if (Size() > 0) {
TextItem *t= (TextItem*) At(0);
t->SetString(s);
} else
Add(new TextItem(s));
}
}
void MenuButtonItem::SetString(char *s)
{
char *cp, buf1[100];
int i;
for (i= 0, cp= s; *cp && *cp != '@'; cp++, i++)
buf1[i]= *cp;
if (*cp == '@') {
buf1[i]= 0;
SetLabel(buf1);
SetShortCut(&cp[1]);
} else {
SetLabel(s);
SetShortCut(0);
}
}
void MenuButtonItem::InputKbd(Token &t)
{
if (Enabled() && Size() > 1) {
TextItem *ti= (TextItem*) At(1);
char *s= ti->AsString();
if (s && upcase[s[1]] == upcase[t.Code & 0x7f])
Control(GetId(), cPartToggle, (void*) 1);
}
}
int MenuButtonItem::Compare(Object *op)
{
return strcmp(AsString(), op->AsString());
}
//---- MouseTracker ------------------------------------------------------------
class MouseTracker: public Command {
VObject *last, *vop;
Menu *menu;
Rectangle exitRect;
public:
MouseTracker(Menu *m, VObject *v, Rectangle er)
{ menu= m; exitRect= er; vop= v; }
void TrackFeedback(Point, Point, bool)
{ }
Command *TrackMouse(TrackPhase, Point, Point, Point);
};
Command *MouseTracker::TrackMouse(TrackPhase atp, Point, Point, Point np)
{
Point pp= vop->GetPortPoint(np);
if (pp.y < 0 && exitRect.IsNotEmpty() && !exitRect.ContainsPoint(pp))
return gNoChanges;
if (menulevel > 1 && (pp.x < 0 || pp.y < 0))
return gNoChanges;
VObject *itemptr= menu->FindAnItem(np);
switch (atp) {
case eTrackPress:
if (itemptr)
itemptr->DoTrackMouse(eTrackPress, np);
break;
case eTrackMove:
if (itemptr != last) {
if (last)
last->DoTrackMouse(eTrackExit, np);
if (itemptr)
itemptr->DoTrackMouse(eTrackPress, np);
last= itemptr;
} else if (itemptr)
itemptr->DoTrackMouse(eTrackMove, np);
break;
case eTrackExit:
case eTrackRelease:
if (itemptr)
itemptr->DoTrackMouse(atp, np);
return gNoChanges;
case eTrackIdle:
break;
}
return this;
}
//---- Menu --------------------------------------------------------------------
NewMetaImpl(Menu,Manager, (TP(view), T(selection), TP(clipper), T(resetAll),
T(dimAll)));
Menu::Menu(char *t, bool da, bool ra, int r, int c, SeqCollection *col) : Manager(t)
{
Init(cIdNone, t, da, ra, r, c, col);
}
Menu::Menu(int id, char *t, bool da, bool ra, int r, int c, SeqCollection *col) : Manager(t)
{
Init(id, t, da, ra, r, c, col);
}
Menu::~Menu()
{
SafeDelete(view);
}
void Menu::Init(int id, char*, bool da, bool ra, int r, int c, SeqCollection *col)
{
if (1) {
if (col == 0)
col= new OrdCollection;
view= new CollectionView(this, col, eCVDontStuckToBorder, r, c);
} else
view= new Box(cIdNone, Point(c,r), gPoint0, eVObjHExpand, col);
view->ResetFlag(eVObjKbdFocus);
selection= cIdNone;
resetAll= ra;
dimAll= da;
SetId(id);
nextHandler= 0;
}
void Menu::SetNextHandler(EvtHandler *eh)
{
nextHandler= eh;
}
EvtHandler *Menu::GetNextHandler()
{
if (nextHandler)
return nextHandler;
return gFirstHandler;
}
VObject *Menu::FindAnItem(Point p)
{
Iter next(GetCollection());
register VObject *vop;
while (vop= (VObject*) next())
if (vop->ContainsPoint(p))
return vop;
return 0;
}
VObject *Menu::FindInitialItem(int id)
{
VObject *vop= 0;
if (id != cIdNone)
if (vop= FindItem(id))
return vop;
return (VObject*) GetCollection()->First();
}
Point Menu::GetInitialPos(Point)
{
return gPoint0;
}
void Menu::SetSelectedItem(int id)
{
selection= id;
}
Window *Menu::DoMakeWindows()
{
return
new Window(this,
clipper= new Clipper(view, cAutoSize, cIdNone, gInkNone),
eWinPulldownMenu,
eWinDefault,
cAutoSize,
GetName()
);
}
int Menu::CheckKey(Token &t)
{
if (view && view->IsKindOf(CollectionView))
((CollectionView*)view)->Update();
if (resetAll)
ResetAll();
if (dimAll)
DisableAll();
if (GetNextHandler())
GetNextHandler()->DoSetupMenu(this);
if (GetCollection()->Size() <= 0)
return cIdNone;
Iter next(GetCollection());
register VObject *vop;
int oldselection= selection;
selection= cIdNone;
while (vop= (VObject*) next())
if (vop->IsKindOf(MenuButtonItem)) {
((MenuButtonItem*)vop)->InputKbd(t);
if (selection != cIdNone)
break;
}
if (selection == cIdNone) {
selection= oldselection;
return cIdNone;
}
return selection;
}
extern Point showdelta;
int Menu::Popup(Point p, VObject *fp, int id, bool showlast,
int menupos, Rectangle exitr)
{
if (resetAll)
ResetAll();
if (dimAll)
DisableAll();
if (GetNextHandler())
GetNextHandler()->DoSetupMenu(this);
if (GetCollection()->Size() <= 0)
return cIdNone;
selection= id;
MakeWindows();
if (TestFlag(eMenuNoScroll)) {
clipper->SetMinExtent(cAutoSize);
} else {
Point e= view->GetMinSize().extent;
if (view->IsKindOf(CollectionView)) {
Rectangle r(((CollectionView*)view)->ItemRect(2,20));
clipper->SetMinExtent(r.origin+r.extent);
} else
clipper->SetMinExtent(Min(Point(200), e));
clipper->Scroll(cPartScrollAbs, gPoint0, FALSE);
}
if (view->IsKindOf(View))
((View*)view)->ClearSelection(FALSE);
Point lp;
GetWindow()->GetMinSize();
VObject *vop= FindInitialItem(selection);
if (vop) {
if (menupos)
lp= vop->contentRect.origin;
else
lp= vop->contentRect.W()+Point(4,0);
}
int oldselection= selection;
selection= cIdNone;
Point pp= view->GetPortPoint(lp);
if (pp == gPoint0) { // this is a hack
pp= gPoint2;
}
OpenAt(fp, p - pp + Point(2,3), TRUE, FALSE);
menulevel++;
if (!showlast)
lp= gPoint_1;
exitr.origin-= showdelta;
view->TrackInContent(lp, Token(), new MouseTracker(this, view, exitr));
menulevel--;
Close();
if (selection == cIdNone) {
selection= oldselection;
return cIdNone;
}
return selection;
}
int Menu::Pulldown(Point p, VObject *vop)
{
return Popup(p, vop, selection, TRUE, FALSE, gRect0);
}
void Menu::Control(int id, int part, void*)
{
if (part == cPartToggle)
selection= id;
}
OStream& Menu::PrintOn(OStream &s)
{
Manager::PrintOn(s);
return s << view SP << selection SP << resetAll SP << dimAll SP;
}
IStream& Menu::ReadFrom(IStream &s)
{
Manager::ReadFrom(s);
return s >> view >> selection >> resetAll >> dimAll;
}
SeqCollection *Menu::GetCollection()
{
if (view->IsKindOf(CollectionView))
return ((CollectionView*)view)->GetCollection();
if (view->IsKindOf(CompositeVObject))
return ((CompositeVObject*)view)->GetList();
return 0;
}
void Menu::SetCollection(SeqCollection *c, bool freeold)
{
if (view->IsKindOf(CollectionView))
((CollectionView*)view)->SetCollection(c, freeold);
}
void Menu::Insert(VObject *mip)
{
GetCollection()->AddFirst(mip);
}
void Menu::InsertItem(char *s, int id)
{
Insert(MakeMenuItem(s, id));
}
void Menu::Append(VObject *mip)
{
GetCollection()->Add(mip);
}
VObject *Menu::FindItem(int id)
{
Iter next(GetCollection());
register VObject *vop;
while (vop= (VObject*) next())
if (vop->GetId() == id)
return vop;
return 0;
}
void Menu::InsertBefore(int id, VObject *mip)
{
VObject *vop= FindItem(id);
if (vop)
GetCollection()->AddBeforePtr(mip, vop);
else
GetCollection()->AddFirst(mip);
}
void Menu::InsertAfter(int id, VObject *mip)
{
VObject *vop= FindItem(id);
if (vop)
GetCollection()->AddAfterPtr(mip, vop);
else
GetCollection()->Add(mip);
}
void Menu::InsertItemAfter(int atId, char *s, int id)
{
InsertAfter(atId, MakeMenuItem(s, id));
}
void Menu::InsertItemBefore(int atId, char *s, int id)
{
InsertBefore(atId, MakeMenuItem(s, id));
}
void Menu::AppendItem(char *s, int id)
{
GetCollection()->Add(MakeMenuItem(s, id));
}
void Menu::AppendItems(char *va_(first), ...)
{
va_list ap;
va_start(ap,va_(first));
InsertVItems(cIdNone, FALSE, va_(first), ap);
va_end(ap);
}
void Menu::InsertItemsBefore(int va_(atId), ...)
{
va_list ap;
va_start(ap,va_(atId));
char *first= va_arg(ap, char*);
InsertVItems(va_(atId), TRUE, first, ap);
va_end(ap);
}
void Menu::InsertItemsAfter(int va_(atId), ...)
{
va_list ap;
va_start(ap,va_(atId));
char *first= va_arg(ap, char*);
InsertVItems(va_(atId), FALSE, first, ap);
va_end(ap);
}
VObject *Menu::MakeMenuItem(char *s, int id)
{
if (strcmp(s, "-") == 0)
return new Separator;
MenuButtonItem *mi= new MenuButtonItem(id, "");
mi->SetString(s);
return mi;
}
void Menu::InsertVItems(int atId, bool before, char *first, va_list ap)
{
SeqCollection *col= GetCollection();
int id= cIdNone;
VObject *vop, *atvop= 0;
if (atId != cIdNone)
atvop= FindItem(atId);
for (int i= 0;; i++) {
char *s= (i == 0) ? first : va_arg(ap, char*);
if (s == 0)
break;
if (strcmp(s, "-"))
id= va_arg(ap, int);
vop= MakeMenuItem(s, id);
if (atvop == 0)
col->Add(vop);
else if (before && i== 0)
col->AddBeforePtr(vop, atvop);
else
col->AddAfterPtr(vop, atvop);
atvop= vop;
}
}
void Menu::EnableAll(bool b)
{
GetCollection()->ForEach(VObject,Enable)(b, FALSE);
}
void Menu::ResetAll()
{
Iter next(GetCollection());
Object *op;
while (op= next())
if (op->IsKindOf(StateButton))
((StateButton*)op)->SetValue(0,FALSE);
}
void Menu::CheckItem(int id, int state, int type)
{
int code= 0;
VObject *vop= FindItem(id);
if (vop) {
StateButton *mi= Guard(vop, StateButton);
if (state)
mi->SetValue(type, FALSE);
else
mi->SetValue(0, FALSE);
}
}
void Menu::ReplaceItem(int id, char *s)
{
VObject *v= FindItem(id);
if (v) {
if (v->IsKindOf(TextItem)) {
TextItem *t= (TextItem*) v;
t->SetString(s);
} else if (v->IsKindOf(MenuButtonItem)) {
MenuButtonItem *mi= (MenuButtonItem*)v;
mi->SetString(s);
}
if (view->IsKindOf(CollectionView))
((CollectionView*)view)->Modified();
}
}
void Menu::ToggleItem(int id, bool toggle, char *toggleTrue, char *toggleFalse)
{
ReplaceItem(id, toggle ? toggleTrue : toggleFalse);
}
void Menu::ToggleItem(int id, bool toggle, char *fmt, char *toggleTrue, char *toggleFalse)
{
ReplaceItem(id, form(fmt, toggle ? toggleTrue : toggleFalse));
}
VObject *Menu::RemoveItem(int id)
{
VObject *vop= FindItem(id);
if (vop) {
VObject *cont= vop->GetContainer();
Menu *m= this;
if (cont && cont->IsKindOf(Menu))
m= (Menu*)cont;
m->GetCollection()->RemovePtr(vop);
}
return vop;
}
void Menu::RemoveAllItems(bool free)
{
// view->ClearSelection();
Collection *cp= GetCollection();
if (free)
cp->FreeAll();
cp->RemoveAll(cp);
}
Menu *Menu::FindMenuItem(int id)
{
VObject *vop= FindItem(id);
if (!vop || !vop->IsKindOf(MenuItem))
return 0;
MenuItem *mip= (MenuItem*)vop;
return mip->MyMenu();
}
void Menu::EnableItem(int id, bool b)
{
VObject *vop= FindItem(id);
if (vop)
vop->Enable(b, FALSE);
}
void Menu::EnableItems(int va_(first), ...)
{
va_list ap;
va_start(ap,va_(first));
register int id;
EnableItem(va_(first));
while (id= va_arg(ap, int))
EnableItem(id);
va_end(ap);
}
void Menu::AppendMenu(Menu *m, int id)
{
Append(new MenuItem(id, new TextItem(m->GetName()), m));
}